#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/crypto.h>
#include <linux/scatterlist.h>
#include <crypto/hash.h>
#include <linux/errno.h>
#include <linux/string.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Tongyi Kernel Module");
MODULE_DESCRIPTION("SM3 Hash Implementation using Linux Kernel Crypto Subsystem");
MODULE_VERSION("1.0");

// 定义SM3哈希值的长度（32字节）
#define SM3_DIGEST_SIZE 32

// 全局变量用于存储哈希算法实例
static struct crypto_shash *tfm;

// 模块初始化函数
static int __init sm3_hash_init(void)
{
    struct shash_desc *shash;
    u8 *input_data;
    u8 output_digest[SM3_DIGEST_SIZE];
    int ret;
    int i;
    
    printk(KERN_INFO "SM3 Hash Module: Loading module\n");
    
    // 根据GBT 32905-2016标准，使用示例数据"abc"
    input_data = "abc";
    
    // 分配SM3哈希算法实例
    tfm = crypto_alloc_shash("sm3", 0, 0);
    if (IS_ERR(tfm)) {
        printk(KERN_ERR "SM3 Hash Module: Failed to allocate SM3 transform\n");
        return PTR_ERR(tfm);
    }
    
    // 计算输入数据长度
    unsigned int input_len = strlen(input_data);
    
    // 分配哈希描述符，大小为哈希算法描述符大小加上算法实例指针
    shash = kmalloc(sizeof(struct shash_desc) + crypto_shash_descsize(tfm), GFP_KERNEL);
    if (!shash) {
        printk(KERN_ERR "SM3 Hash Module: Failed to allocate shash descriptor\n");
        ret = -ENOMEM;
        goto cleanup_tfm;
    }
    
    // 初始化哈希描述符
    shash->tfm = tfm;
    
    // 初始化哈希上下文
    ret = crypto_shash_init(shash);
    if (ret) {
        printk(KERN_ERR "SM3 Hash Module: Failed to initialize hash context\n");
        kfree(shash);
        goto cleanup_tfm;
    }
    
    // 更新哈希值，传入输入数据
    ret = crypto_shash_update(shash, input_data, input_len);
    if (ret) {
        printk(KERN_ERR "SM3 Hash Module: Failed to update hash value\n");
        kfree(shash);
        goto cleanup_tfm;
    }
    
    // 计算最终的哈希值
    ret = crypto_shash_final(shash, output_digest);
    if (ret) {
        printk(KERN_ERR "SM3 Hash Module: Failed to compute final hash value\n");
        kfree(shash);
        goto cleanup_tfm;
    }
    
    // 打印输入数据
    printk(KERN_INFO "SM3 Hash Module: Input data: %s\n", input_data);
    printk(KERN_INFO "SM3 Hash Module: Input length: %u bytes\n", input_len);
    
    // 打印计算得到的SM3哈希值（以十六进制格式）
    printk(KERN_INFO "SM3 Hash Module: SM3 Hash Result: ");
    for (i = 0; i < SM3_DIGEST_SIZE; i++) {
        printk("%02x", output_digest[i]);
    }
    printk("\n");
    
    // 验证结果是否符合GBT 32905-2016标准
    // 标准中"abc"的SM3哈希值应该是:
    // 66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0
    u8 expected_digest[SM3_DIGEST_SIZE] = {
        0x66, 0xc7, 0xf0, 0xf4, 0x62, 0xee, 0xed, 0xd9, 0xd1, 0xf2, 0xd4, 0x6b, 0xdc, 0x10, 0xe4, 0xe2,
        0x41, 0x67, 0xc4, 0x87, 0x5c, 0xf2, 0xf7, 0xa2, 0x29, 0x7d, 0xa0, 0x2b, 0x8f, 0x4b, 0xa8, 0xe0
    };
    
    // 验证计算结果是否与标准值一致
    if (memcmp(output_digest, expected_digest, SM3_DIGEST_SIZE) == 0) {
        printk(KERN_INFO "SM3 Hash Module: Hash verification PASSED - matches GBT 32905-2016 standard\n");
    } else {
        printk(KERN_WARNING "SM3 Hash Module: Hash verification FAILED - does not match standard\n");
    }
    
    // 释放哈希描述符
    kfree(shash);
    
    printk(KERN_INFO "SM3 Hash Module: Module loaded successfully\n");
    return 0;

cleanup_tfm:
    crypto_free_shash(tfm);
    return ret;
}

// 模块退出函数
static void __exit sm3_hash_exit(void)
{
    printk(KERN_INFO "SM3 Hash Module: Unloading module\n");
    
    // 释放哈希算法实例
    crypto_free_shash(tfm);
    
    printk(KERN_INFO "SM3 Hash Module: Module unloaded successfully\n");
}

// 注册模块初始化和退出函数
module_init(sm3_hash_init);
module_exit(sm3_hash_exit);